﻿#region Usings

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.IO;
using System.Collections.Generic;

#endregion

public partial class SyntaxHighlighter_Admin : System.Web.UI.Page
{
    #region Private members

    private static ExtensionSettings folderSettings = null;
    private static ExtensionSettings brushSettings = null;
    private static ExtensionSettings styleSettings = null;
    private string extensionName = "SyntaxHighlighter";

    #endregion

    #region Page Generation

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            LoadSettings();
            BindForm();
        }
    }

    /// <summary>
    /// populate the various form elements with data. 
    /// The brushes and styles settings will only be shown if the
    /// scripts and styles folder exists.
    /// </summary>
    private void BindForm()
    {
        // Folders settings
        btnFolderSave.Text = Resources.labels.saveSettings;
        txtScripts.Text = folderSettings.GetSingleValue("Scripts");
        txtStyles.Text = folderSettings.GetSingleValue("Styles");
        folderInfo.InnerHtml = folderSettings.Help;

        // Brushes settings
        btnBrushSave.Text = Resources.labels.saveSettings;
        btnBrushUpdate.Text = "Update Brush List";
        brushesBox.Items.Clear();
        if (brushSettings != null)
        {
            // Retrieving all brushes and setting their selected status
            foreach (DataColumn brush in brushSettings.GetDataTable().Columns)
            {
                ListItem item = new ListItem(brush.ColumnName.Replace("shBrush", "").Replace(".js", ""));
                item.Value = brush.ColumnName;
                item.Selected = bool.Parse(brushSettings.GetSingleValue(brush.ColumnName));
                brushesBox.Items.Add(item);
            }
        }

        if (brushesBox.Items.Count == 0)
            brushContainer.Visible = false;
        else
        {
            brushContainer.Visible = true;
            brushInfo.InnerHtml = brushSettings.Help;
        }

        // Styles settings
        btnStylesSave.Text = Resources.labels.saveSettings;
        btnStylesUpdate.Text = "Update Style List";
        stylesList.Items.Clear();
        if (styleSettings != null)
        {
            // Retrieving all styles and adding them to the dropdownlist
            for (int i = 0; i < styleSettings.GetDataTable().Columns.Count; i++)
            {
                DataColumn style = styleSettings.GetDataTable().Columns[i];
                ListItem item = new ListItem(style.ColumnName.Replace("shTheme", "").Replace(".css", ""));
                item.Value = style.ColumnName;
                if (style.ColumnName != "Style")
                    stylesList.Items.Add(item);
                if (styleSettings.GetSingleValue("Style") == style.ColumnName)
                    stylesList.SelectedIndex = i;
            }
        }

        if (stylesList.Items.Count == 0)
        {
            stylesContainer.Visible = false;
        }
        else
        {
            stylesContainer.Visible = true;
            styleInfo.InnerHtml = styleSettings.Help;
        }

        // Brush aliases
        if (brushesBox.Items.Count > 0)
        {
            BuildAliasesTable();
            aliasesInfo.InnerHtml = "Listed are the aliases that can be used for each brush. <br />Only brushes that are selected above will be shown.";
            aliasesContainer.Visible = true;
        }
        else
            aliasesContainer.Visible = false;

    }

    #endregion

    #region Button Event handlers

    /// <summary>
    /// Saves the relative path to the scripts and styles folders.
    /// Removes the settings for Brushes and Styles and reloads the extension.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnFolderSave_Click(object sender, EventArgs e)
    {
        // Making sure that the folder settings are loaded before updating them
        // with the new folder values.
        LoadSettings();
        folderSettings.UpdateScalarValue("Scripts", txtScripts.Text);
        folderSettings.UpdateScalarValue("Styles", txtStyles.Text);
        ExtensionManager.Save();

        // Removes the Brushes and Styles settings
        RemoveSetting("Brushes");
        RemoveSetting("Styles");
        brushSettings = null;
        styleSettings = null;

        // Reloads the extension on page refresh
        ExtensionManager.ChangeStatus(extensionName, false);
        ExtensionManager.ChangeStatus(extensionName, true);

        // Reloads the page
        Response.Redirect(Request.RawUrl);
    }

    /// <summary>
    /// Updates the selected status of all the brushes.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnBrushSave_Click(object sender, EventArgs e)
    {
        foreach (ListItem item in brushesBox.Items)
        {
            brushSettings.UpdateScalarValue(item.Value, item.Selected.ToString());
        }

        ExtensionManager.SaveSettings(extensionName, brushSettings);
        Response.Redirect(Request.RawUrl);
    }

    /// <summary>
    /// Reloads the brushes from the scripts folder. 
    /// Will reset all brushes to selected status.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnBrushUpdate_Click(object sender, EventArgs e)
    {
        RemoveSetting("Brushes");

        ExtensionManager.ChangeStatus(extensionName, false);
        ExtensionManager.ChangeStatus(extensionName, true);
        Response.Redirect(Request.RawUrl);

    }

    /// <summary>
    /// Saves the style to use for the SyntaxHighlighter
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnStylesSave_Click(object sender, EventArgs e)
    {
        styleSettings = ExtensionManager.GetSettings(extensionName, "Styles");
        foreach (ListItem item in stylesList.Items)
        {
            if (stylesList.SelectedItem.Value == item.Value)
            {
                styleSettings.UpdateScalarValue("Style", item.Value);
            }
        }

        ExtensionManager.SaveSettings(extensionName, styleSettings);
        Response.Redirect(Request.RawUrl);
    }

    /// <summary>
    /// Reloads the styles from the styles folder.
    /// Will reset the chosen style to be the default style.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnStylesUpdate_Click(object sender, EventArgs e)
    {
        RemoveSetting("Styles");
        stylesList.Items.Clear();

        ExtensionManager.ChangeStatus(extensionName, false);
        ExtensionManager.ChangeStatus(extensionName, true);
        Response.Redirect(Request.RawUrl);
    }

    #endregion

    #region Private methods

    /// <summary>
    /// Loads the folder-, brush- and stylesettings.
    /// </summary>
    private void LoadSettings()
    {
        if (folderSettings == null)
            folderSettings = ExtensionManager.GetSettings(extensionName, "Folders");
        if (brushSettings == null)
            brushSettings = ExtensionManager.GetSettings(extensionName, "Brushes");
        if (styleSettings == null)
            styleSettings = ExtensionManager.GetSettings(extensionName, "Styles");
    }

    /// <summary>
    /// Removes a setting from the extensions storage.
    /// This is a prerequisite to be able to reload the settings values.
    /// </summary>
    /// <param name="settingName">The setting to remove</param>
    private void RemoveSetting(string settingName)
    {
        foreach (ManagedExtension x in ExtensionManager.Extensions)
        {
            if (x.Name == extensionName)
            {
                if (x.Initialized(settingName))
                {
                    foreach (ExtensionSettings y in x.Settings)
                    {
                        if (y.Name == settingName)
                        {
                            x.Settings.Remove(y);
                            break;
                        }
                    }
                    ExtensionManager.SaveToStorage(x);
                }
                break;
            }
        }
    }

    /// <summary>
    /// Adds the rows to the table with brush aliases. 
    /// Only adds aliases for selected brushes.
    /// </summary>
    private void BuildAliasesTable()
    {
        // Making sure the scripts folder exists before trying to read files.
        DirectoryInfo info = new DirectoryInfo(HttpContext.Current.Server.MapPath("~/" + folderSettings.GetSingleValue("Scripts")));
        if (info.Exists)
        {
            if (brushSettings != null)
            {
                DataTable dt = brushSettings.GetDataTable();
                object[] itemArray = dt.Rows[0].ItemArray;
                // Iterate through all the brushes
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    // Checks if the brush is selected
                    if (bool.Parse(itemArray[i].ToString()))
                    {
                        DataColumn brush = dt.Columns[i];
                        string brushName = brush.ColumnName.Replace("shBrush", "").Replace(".js", "");
                        // Opens the brush file
                        StreamReader reader = new StreamReader(File.Open(
                            HttpContext.Current.Server.MapPath("~/" + 
                            folderSettings.GetSingleValue("Scripts")) + 
                            "/" + brush.ColumnName, FileMode.Open));
                        string temp;
                        // Read through the brush file one line at a time
                        while ((temp = reader.ReadLine()) != null)
                        {
                            // Checks if the line contains the aliases
                            if (temp.StartsWith("SyntaxHighlighter.brushes." + brushName + ".aliases"))
                            {
                                // Extract the aliases and strip out unwanted elements
                                string aliases = temp.Substring(temp.LastIndexOf('['));
                                aliases = aliases.Replace("[", "");
                                aliases = aliases.Replace("];", "");
                                aliases = aliases.Replace("'", "");

                                // Make and add the tablerow
                                TableRow tr = new TableRow();
                                TableCell name = new TableCell();
                                name.Text = brushName;
                                tr.Cells.Add(name);

                                TableCell alias = new TableCell();
                                alias.Text = aliases;
                                tr.Cells.Add(alias);

                                aliasesTable.Rows.Add(tr);
                            }
                        }
                        reader.Close();
                    }
                }
            }

        }
    }

    #endregion


}
